packages = c('rgdal', 'maptools', 'raster','spatstat', 'tmap', 'sf', 'tidyverse', 'SpatialAcc', 'tbart') 
for (p in packages){ 
  if(!require(p, character.only = T)){ 
    install.packages(p) } 
  library(p,character.only = T) }
package <U+393C><U+3E31>SpatialAcc<U+393C><U+3E32> was built under R version 3.5.3package <U+393C><U+3E31>tbart<U+393C><U+3E32> was built under R version 3.5.3

Singapore Planning Subzone (MP14_SUBZONE_WEB_PL)

mpsz = st_read(dsn = "data", layer = "MP14_SUBZONE_WEB_PL")
Reading layer `MP14_SUBZONE_WEB_PL' from data source `C:\Users\d-ebb\OneDrive\Documents\GitHub\IS415-Neighbourhood-WatchDocs\data' using driver `ESRI Shapefile'
Simple feature collection with 323 features and 15 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 2667.538 ymin: 15748.72 xmax: 56396.44 ymax: 50256.33
epsg (SRID):    NA
proj4string:    +proj=tmerc +lat_0=1.366666666666667 +lon_0=103.8333333333333 +k=1 +x_0=28001.642 +y_0=38744.572 +datum=WGS84 +units=m +no_defs

Singapore Residents by Subzone, Age Group and Sex (Gender)

population = read_csv("data/respopagsex2000to2017.csv")
Parsed with column specification:
cols(
  PA = col_character(),
  SZ = col_character(),
  AG = col_character(),
  Sex = col_character(),
  Pop = col_double(),
  Time = col_double()
)

Singapore Residents by Subzone, Age Group and Sex, June 2017 (Gender)

popage2017pre <- population %>%
  filter(Time == 2017) %>%
  filter(AG == "65_to_69" | AG == "70_to_74" | AG == "75_to_79" | AG == "80_to_84" | AG == "85_and_over") %>%
  group_by(SZ)
popage2017pre_added <- aggregate(Pop ~ SZ, popage2017pre, sum)

Total Number of Clinics in Singapore

clinics = read_csv("data/clinics_hcidirectory.csv")
Parsed with column specification:
cols(
  clinic_name = col_character(),
  address = col_character(),
  postal_code = col_character(),
  X = col_double(),
  Y = col_double(),
  LAT = col_double(),
  LONG = col_double()
)
clinics_essentials <- c("clinic_name", "address", "LAT", "LONG", "X", "Y") # remove postal code
clinics <- clinics[clinics_essentials]

Total Number of TCM Clinics in Singapore

tcm = read_csv("data/tcm_tcmboard.csv")
Parsed with column specification:
cols(
  tcm_physician_name = col_character(),
  registration_no = col_character(),
  tcm_place_name = col_character(),
  tcm_address = col_character(),
  postal_code = col_character(),
  X = col_double(),
  Y = col_double(),
  LAT = col_double(),
  LONG = col_double()
)
tcm <- tcm[!duplicated(tcm$tcm_place_name), ]
  
tcm_essentials <- c("tcm_place_name", "tcm_address", "LAT", "LONG", "X", "Y")
tcm <- tcm[tcm_essentials]
names(tcm)[names(tcm) == "tcm_place_name"] <- "clinic_name"
names(tcm)[names(tcm) == "tcm_address"] <- "address"

Combine TCM and clinics

clinics_combined <- rbind(clinics, tcm)

Number of HDB blocks per planning subzone

HDB = read_csv("data/hdb_property_information.csv")
Parsed with column specification:
cols(
  blk_no_street = col_character(),
  total_dwelling_units = col_double(),
  `1room_sold` = col_double(),
  `2room_sold` = col_double(),
  `3room_sold` = col_double(),
  `4room_sold` = col_double(),
  `5room_sold` = col_double(),
  exec_sold = col_double(),
  multigen_sold = col_double(),
  studio_apartment_sold = col_double(),
  `1room_rental` = col_double(),
  `2room_rental` = col_double(),
  `3room_rental` = col_double(),
  other_room_rental = col_double(),
  postal_code = col_character(),
  X = col_double(),
  Y = col_double(),
  LAT = col_double(),
  LONG = col_double()
)
HDB_sf <- st_as_sf(HDB, coords = c("X", "Y"), crs = st_crs(mpsz))

Residents by Age Group & Type of Dwelling, Annual

popByDwelling = read_csv("data/residents-by-age-group-and-type-of-dwelling-detailed-categories-annual.csv")
Parsed with column specification:
cols(
  year = col_double(),
  level_1 = col_character(),
  level_2 = col_character(),
  level_3 = col_character(),
  value = col_double()
)

Residents by Age Group & Type of Dwelling, Annual 2017

popByDwelling2017 <- popByDwelling %>%
  filter(year == 2017) %>%
  filter(level_1 == "65-69 Years" 
         | level_1 == "85 Years & Over" 
         | level_1 == "70-74 Years" 
         | level_1 == "75-79 Years"  
         | level_1 == "80-84 Years") %>%
  group_by(level_3)
popByDwelling2017
popByDwelling2017_added <- aggregate(value ~ level_3, popByDwelling2017, sum)

No. of blocks per subzone

mpsz_HDB <- st_join(HDB_sf,mpsz)
mpsz_HDB$`1_2room_total` <- mpsz_HDB$`1room_sold` + mpsz_HDB$`2room_sold` + mpsz_HDB$`1room_rental` + mpsz_HDB$`2room_rental`
mpsz_HDB_1_2_room = aggregate(mpsz_HDB$`1_2room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_1_2_room' = 'x') 
mpsz_HDB$`3room_total` <- mpsz_HDB$`3room_sold` + mpsz_HDB$`3room_rental` + mpsz_HDB$`other_room_rental`
mpsz_HDB_3_room_added = aggregate(mpsz_HDB$`3room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_3_room' = 'x') 
mpsz_HDB$`4room_total` <- mpsz_HDB$`4room_sold`
mpsz_HDB_4_room_added = aggregate(mpsz_HDB$`4room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_4_room' = 'x') 
mpsz_HDB$`5room_exec_total` <- mpsz_HDB$`5room_sold` + mpsz_HDB$`exec_sold`
mpsz_HDB_5_room_exec_added = aggregate(mpsz_HDB$`5room_exec_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_5_room_exec' = 'x')   
mpsz_HDB_added <- left_join(mpsz_HDB_1_2_room, mpsz_HDB_3_room_added, by ='SUBZONE') %>%
  left_join(., mpsz_HDB_4_room_added, by = 'SUBZONE') %>%
  left_join(., mpsz_HDB_5_room_exec_added, by = 'SUBZONE')
mpsz_HDB_added$`total_units` <- mpsz_HDB_added$`No_of_1_2_room` + mpsz_HDB_added$`No_of_3_room` + mpsz_HDB_added$`No_of_4_room` + mpsz_HDB_added$`No_of_5_room`
total_1_2_room_units <- sum(mpsz_HDB_added$No_of_1_2_room) 
total_3_room_units <- sum(mpsz_HDB_added$No_of_3_room) 
total_4_room_units <- sum(mpsz_HDB_added$No_of_4_room) 
total_5_room_exec_units <- sum(mpsz_HDB_added$No_of_5_room_exec) 

No. of elderly per block in every subzone

total_1_2_room_units <- sum(mpsz_HDB_added$No_of_1_2_room) 
total_3_room_units <- sum(mpsz_HDB_added$No_of_3_room) 
total_4_room_units <- sum(mpsz_HDB_added$No_of_4_room) 
total_5_room_units <- sum(mpsz_HDB_added$No_of_5_room) 
mpsz_HDB$No_of_Elderly_in_block_1_2 <- ifelse(mpsz_HDB$`1_2room_total` == 0, 0, mpsz_HDB$`1_2room_total`/total_1_2_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 1- And 2-Room Flats"]
mpsz_HDB$No_of_Elderly_in_block_3 <- ifelse(mpsz_HDB$`3room_total` == 0, 0, mpsz_HDB$`3room_total`/total_3_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 3-Room Flats"] 
mpsz_HDB$No_of_Elderly_in_block_4 <- ifelse(mpsz_HDB$`4room_total` == 0, 0, mpsz_HDB$`4room_total`/total_4_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 4-Room Flats"]
mpsz_HDB$No_of_Elderly_in_block_5 <- ifelse(mpsz_HDB$`5room_exec_total` == 0, 0, mpsz_HDB$`5room_exec_total`/total_5_room_exec_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 5-Room And Executive Flats"]
                                    
mpsz_HDB$No_of_Elderly_in_block <- mpsz_HDB$No_of_Elderly_in_block_1_2 + mpsz_HDB$No_of_Elderly_in_block_3 + mpsz_HDB$No_of_Elderly_in_block_4 + mpsz_HDB$No_of_Elderly_in_block_5
mpsz_HDB$No_of_Elderly_in_block <- round(mpsz_HDB$No_of_Elderly_in_block)
clinics_combined <- st_as_sf(clinics_combined, coords = c("X", "Y"))
class(clinics_combined)
[1] "sf"         "tbl_df"     "tbl"        "data.frame"
#assign capacity of 2 per clinic
clinics_combined['capacity'] <- 2
mpsz_HDB_coords <- mpsz_HDB %>% st_coordinates() 
clinics_combined_coords <- clinics_combined %>% st_coordinates()
dm <- distance(mpsz_HDB_coords, clinics_combined_coords)
acc_hansen <- data.frame(ac(mpsz_HDB$No_of_Elderly_in_block, clinics_combined$capacity, dm, power=0.01, family="Hansen"))
colnames(acc_hansen) <- "accHansen"
acc_hansen <- tbl_df(acc_hansen)
HDB_acc <- bind_cols(mpsz_HDB, acc_hansen)
tmap_mode("view")
tmap mode set to interactive viewing
tm_shape(mpsz_HDB)+
  tm_symbols(size = 0.1)+
tm_shape(HDB_acc)+
tm_bubbles(col = "accHansen",
           n=5,
           style = "quantile",
           size = 0.1,
           border.col = "black",
           border.lwd = 1)
mpsz_HDB_sp <- as(mpsz_HDB, "Spatial")
clinics_combined_sp <- as(clinics_combined, "Spatial")
proj4string(clinics_combined_sp) <- CRS("+init=epsg:3414")
spTransform(mpsz_HDB_sp, "+init=epsg:3414")
class       : SpatialPointsDataFrame 
features    : 9966 
extent      : 11519.15, 45192.3, 28097.64, 48682.98  (xmin, xmax, ymin, ymax)
coord. ref. : +init=epsg:3414 +proj=tmerc +lat_0=1.366666666666667 +lon_0=103.8333333333333 +k=1 +x_0=28001.642 +y_0=38744.572 +ellps=WGS84 +units=m +no_defs 
variables   : 41
names       :    blk_no_street, total_dwelling_units, X1room_sold, X2room_sold, X3room_sold, X4room_sold, X5room_sold, exec_sold, multigen_sold, studio_apartment_sold, X1room_rental, X2room_rental, X3room_rental, other_room_rental, postal_code, ... 
min values  :       1 BEACH RD,                    2,           0,           0,           0,           0,           0,         0,             0,                     0,             0,             0,             0,                 0,      050004, ... 
max values  : 9B BOON TIONG RD,                  584,         255,         225,         528,         316,         164,       135,            66,                   210,           520,           452,           114,                32,         NIL, ... 
mpsz_HDB_sp <- mpsz_HDB_sp[mpsz_HDB_sp@data$SUBZONE_N=="TAMAN JURONG", ]
eucDist <- euc.dists(mpsz_HDB_sp, clinics_combined_sp)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgbWVzc2FnZT0gRkFMU0V9DQpwYWNrYWdlcyA9IGMoJ3JnZGFsJywgJ21hcHRvb2xzJywgJ3Jhc3RlcicsJ3NwYXRzdGF0JywgJ3RtYXAnLCAnc2YnLCAndGlkeXZlcnNlJywgJ1NwYXRpYWxBY2MnLCAndGJhcnQnKSANCmZvciAocCBpbiBwYWNrYWdlcyl7IA0KICBpZighcmVxdWlyZShwLCBjaGFyYWN0ZXIub25seSA9IFQpKXsgDQogICAgaW5zdGFsbC5wYWNrYWdlcyhwKSB9IA0KICBsaWJyYXJ5KHAsY2hhcmFjdGVyLm9ubHkgPSBUKSB9DQpgYGANCg0KU2luZ2Fwb3JlIFBsYW5uaW5nIFN1YnpvbmUgKE1QMTRfU1VCWk9ORV9XRUJfUEwpDQpgYGB7cn0NCm1wc3ogPSBzdF9yZWFkKGRzbiA9ICJkYXRhIiwgbGF5ZXIgPSAiTVAxNF9TVUJaT05FX1dFQl9QTCIpDQoNCmBgYA0KDQpTaW5nYXBvcmUgUmVzaWRlbnRzIGJ5IFN1YnpvbmUsIEFnZSBHcm91cCBhbmQgU2V4IChHZW5kZXIpDQpgYGB7cn0NCnBvcHVsYXRpb24gPSByZWFkX2NzdigiZGF0YS9yZXNwb3BhZ3NleDIwMDB0bzIwMTcuY3N2IikNCg0KYGBgDQoNClNpbmdhcG9yZSBSZXNpZGVudHMgYnkgU3Viem9uZSwgQWdlIEdyb3VwIGFuZCBTZXgsIEp1bmUgMjAxNyAoR2VuZGVyKQ0KYGBge3J9DQpwb3BhZ2UyMDE3cHJlIDwtIHBvcHVsYXRpb24gJT4lDQogIGZpbHRlcihUaW1lID09IDIwMTcpICU+JQ0KICBmaWx0ZXIoQUcgPT0gIjY1X3RvXzY5IiB8IEFHID09ICI3MF90b183NCIgfCBBRyA9PSAiNzVfdG9fNzkiIHwgQUcgPT0gIjgwX3RvXzg0IiB8IEFHID09ICI4NV9hbmRfb3ZlciIpICU+JQ0KICBncm91cF9ieShTWikNCg0KcG9wYWdlMjAxN3ByZV9hZGRlZCA8LSBhZ2dyZWdhdGUoUG9wIH4gU1osIHBvcGFnZTIwMTdwcmUsIHN1bSkNCg0KYGBgDQoNCg0KVG90YWwgTnVtYmVyIG9mIENsaW5pY3MgaW4gU2luZ2Fwb3JlDQpgYGB7cn0NCmNsaW5pY3MgPSByZWFkX2NzdigiZGF0YS9jbGluaWNzX2hjaWRpcmVjdG9yeS5jc3YiKQ0KDQpjbGluaWNzX2Vzc2VudGlhbHMgPC0gYygiY2xpbmljX25hbWUiLCAiYWRkcmVzcyIsICJMQVQiLCAiTE9ORyIsICJYIiwgIlkiKSAjIHJlbW92ZSBwb3N0YWwgY29kZQ0KDQpjbGluaWNzIDwtIGNsaW5pY3NbY2xpbmljc19lc3NlbnRpYWxzXQ0KYGBgDQoNCg0KVG90YWwgTnVtYmVyIG9mIFRDTSBDbGluaWNzIGluIFNpbmdhcG9yZQ0KYGBge3J9DQp0Y20gPSByZWFkX2NzdigiZGF0YS90Y21fdGNtYm9hcmQuY3N2IikNCg0KdGNtIDwtIHRjbVshZHVwbGljYXRlZCh0Y20kdGNtX3BsYWNlX25hbWUpLCBdDQogIA0KdGNtX2Vzc2VudGlhbHMgPC0gYygidGNtX3BsYWNlX25hbWUiLCAidGNtX2FkZHJlc3MiLCAiTEFUIiwgIkxPTkciLCAiWCIsICJZIikNCg0KdGNtIDwtIHRjbVt0Y21fZXNzZW50aWFsc10NCg0KbmFtZXModGNtKVtuYW1lcyh0Y20pID09ICJ0Y21fcGxhY2VfbmFtZSJdIDwtICJjbGluaWNfbmFtZSINCm5hbWVzKHRjbSlbbmFtZXModGNtKSA9PSAidGNtX2FkZHJlc3MiXSA8LSAiYWRkcmVzcyINCmBgYA0KDQoNCkNvbWJpbmUgVENNIGFuZCBjbGluaWNzDQpgYGB7cn0NCmNsaW5pY3NfY29tYmluZWQgPC0gcmJpbmQoY2xpbmljcywgdGNtKQ0KDQpgYGANCg0KTnVtYmVyIG9mIEhEQiBibG9ja3MgcGVyIHBsYW5uaW5nIHN1YnpvbmUNCmBgYHtyfQ0KSERCID0gcmVhZF9jc3YoImRhdGEvaGRiX3Byb3BlcnR5X2luZm9ybWF0aW9uLmNzdiIpDQoNCkhEQl9zZiA8LSBzdF9hc19zZihIREIsIGNvb3JkcyA9IGMoIlgiLCAiWSIpLCBjcnMgPSBzdF9jcnMobXBzeikpDQoNCmBgYA0KDQpSZXNpZGVudHMgYnkgQWdlIEdyb3VwICYgVHlwZSBvZiBEd2VsbGluZywgQW5udWFsDQpgYGB7cn0NCnBvcEJ5RHdlbGxpbmcgPSByZWFkX2NzdigiZGF0YS9yZXNpZGVudHMtYnktYWdlLWdyb3VwLWFuZC10eXBlLW9mLWR3ZWxsaW5nLWRldGFpbGVkLWNhdGVnb3JpZXMtYW5udWFsLmNzdiIpDQoNCmBgYA0KDQpSZXNpZGVudHMgYnkgQWdlIEdyb3VwICYgVHlwZSBvZiBEd2VsbGluZywgQW5udWFsIDIwMTcNCmBgYHtyfQ0KcG9wQnlEd2VsbGluZzIwMTcgPC0gcG9wQnlEd2VsbGluZyAlPiUNCiAgZmlsdGVyKHllYXIgPT0gMjAxNykgJT4lDQogIGZpbHRlcihsZXZlbF8xID09ICI2NS02OSBZZWFycyIgDQogICAgICAgICB8IGxldmVsXzEgPT0gIjg1IFllYXJzICYgT3ZlciIgDQogICAgICAgICB8IGxldmVsXzEgPT0gIjcwLTc0IFllYXJzIiANCiAgICAgICAgIHwgbGV2ZWxfMSA9PSAiNzUtNzkgWWVhcnMiICANCiAgICAgICAgIHwgbGV2ZWxfMSA9PSAiODAtODQgWWVhcnMiKSAlPiUNCiAgZ3JvdXBfYnkobGV2ZWxfMykNCg0KcG9wQnlEd2VsbGluZzIwMTcNCnBvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkIDwtIGFnZ3JlZ2F0ZSh2YWx1ZSB+IGxldmVsXzMsIHBvcEJ5RHdlbGxpbmcyMDE3LCBzdW0pDQoNCmBgYA0KDQoNCk5vLiBvZiBibG9ja3MgcGVyIHN1YnpvbmUNCmBgYHtyfQ0KbXBzel9IREIgPC0gc3Rfam9pbihIREJfc2YsbXBzeikNCg0KbXBzel9IREIkYDFfMnJvb21fdG90YWxgIDwtIG1wc3pfSERCJGAxcm9vbV9zb2xkYCArIG1wc3pfSERCJGAycm9vbV9zb2xkYCArIG1wc3pfSERCJGAxcm9vbV9yZW50YWxgICsgbXBzel9IREIkYDJyb29tX3JlbnRhbGANCg0KbXBzel9IREJfMV8yX3Jvb20gPSBhZ2dyZWdhdGUobXBzel9IREIkYDFfMnJvb21fdG90YWxgLCBieT1saXN0KFNVQlpPTkU9bXBzel9IREIkU1VCWk9ORV9OKSwgRlVOPXN1bSkgJT4lDQogIHJlbmFtZSgnTm9fb2ZfMV8yX3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDNyb29tX3RvdGFsYCA8LSBtcHN6X0hEQiRgM3Jvb21fc29sZGAgKyBtcHN6X0hEQiRgM3Jvb21fcmVudGFsYCArIG1wc3pfSERCJGBvdGhlcl9yb29tX3JlbnRhbGANCg0KbXBzel9IREJfM19yb29tX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGAzcm9vbV90b3RhbGAsIGJ5PWxpc3QoU1VCWk9ORT1tcHN6X0hEQiRTVUJaT05FX04pLCBGVU49c3VtKSAlPiUNCiAgcmVuYW1lKCdOb19vZl8zX3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDRyb29tX3RvdGFsYCA8LSBtcHN6X0hEQiRgNHJvb21fc29sZGANCg0KbXBzel9IREJfNF9yb29tX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGA0cm9vbV90b3RhbGAsIGJ5PWxpc3QoU1VCWk9ORT1tcHN6X0hEQiRTVUJaT05FX04pLCBGVU49c3VtKSAlPiUNCiAgcmVuYW1lKCdOb19vZl80X3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDVyb29tX2V4ZWNfdG90YWxgIDwtIG1wc3pfSERCJGA1cm9vbV9zb2xkYCArIG1wc3pfSERCJGBleGVjX3NvbGRgDQoNCm1wc3pfSERCXzVfcm9vbV9leGVjX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGA1cm9vbV9leGVjX3RvdGFsYCwgYnk9bGlzdChTVUJaT05FPW1wc3pfSERCJFNVQlpPTkVfTiksIEZVTj1zdW0pICU+JQ0KICByZW5hbWUoJ05vX29mXzVfcm9vbV9leGVjJyA9ICd4JykgICANCg0KbXBzel9IREJfYWRkZWQgPC0gbGVmdF9qb2luKG1wc3pfSERCXzFfMl9yb29tLCBtcHN6X0hEQl8zX3Jvb21fYWRkZWQsIGJ5ID0nU1VCWk9ORScpICU+JQ0KICBsZWZ0X2pvaW4oLiwgbXBzel9IREJfNF9yb29tX2FkZGVkLCBieSA9ICdTVUJaT05FJykgJT4lDQogIGxlZnRfam9pbiguLCBtcHN6X0hEQl81X3Jvb21fZXhlY19hZGRlZCwgYnkgPSAnU1VCWk9ORScpDQoNCm1wc3pfSERCX2FkZGVkJGB0b3RhbF91bml0c2AgPC0gbXBzel9IREJfYWRkZWQkYE5vX29mXzFfMl9yb29tYCArIG1wc3pfSERCX2FkZGVkJGBOb19vZl8zX3Jvb21gICsgbXBzel9IREJfYWRkZWQkYE5vX29mXzRfcm9vbWAgKyBtcHN6X0hEQl9hZGRlZCRgTm9fb2ZfNV9yb29tYA0KYGBgDQoNCmBgYHtyfQ0KdG90YWxfMV8yX3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzFfMl9yb29tKSANCnRvdGFsXzNfcm9vbV91bml0cyA8LSBzdW0obXBzel9IREJfYWRkZWQkTm9fb2ZfM19yb29tKSANCnRvdGFsXzRfcm9vbV91bml0cyA8LSBzdW0obXBzel9IREJfYWRkZWQkTm9fb2ZfNF9yb29tKSANCnRvdGFsXzVfcm9vbV9leGVjX3VuaXRzIDwtIHN1bShtcHN6X0hEQl9hZGRlZCROb19vZl81X3Jvb21fZXhlYykgDQoNCmBgYA0KDQoNCk5vLiBvZiBlbGRlcmx5IHBlciBibG9jayBpbiBldmVyeSBzdWJ6b25lDQpgYGB7cn0NCnRvdGFsXzFfMl9yb29tX3VuaXRzIDwtIHN1bShtcHN6X0hEQl9hZGRlZCROb19vZl8xXzJfcm9vbSkgDQp0b3RhbF8zX3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzNfcm9vbSkgDQp0b3RhbF80X3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzRfcm9vbSkgDQp0b3RhbF81X3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzVfcm9vbSkgDQoNCm1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMV8yIDwtIGlmZWxzZShtcHN6X0hEQiRgMV8ycm9vbV90b3RhbGAgPT0gMCwgMCwgbXBzel9IREIkYDFfMnJvb21fdG90YWxgL3RvdGFsXzFfMl9yb29tX3VuaXRzKSAqIHBvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkJHZhbHVlW3BvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkJGxldmVsXzM9PSJIREIgMS0gQW5kIDItUm9vbSBGbGF0cyJdDQoNCm1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMyA8LSBpZmVsc2UobXBzel9IREIkYDNyb29tX3RvdGFsYCA9PSAwLCAwLCBtcHN6X0hEQiRgM3Jvb21fdG90YWxgL3RvdGFsXzNfcm9vbV91bml0cykgKiBwb3BCeUR3ZWxsaW5nMjAxN19hZGRlZCR2YWx1ZVtwb3BCeUR3ZWxsaW5nMjAxN19hZGRlZCRsZXZlbF8zPT0iSERCIDMtUm9vbSBGbGF0cyJdIA0KDQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzQgPC0gaWZlbHNlKG1wc3pfSERCJGA0cm9vbV90b3RhbGAgPT0gMCwgMCwgbXBzel9IREIkYDRyb29tX3RvdGFsYC90b3RhbF80X3Jvb21fdW5pdHMpICogcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkdmFsdWVbcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkbGV2ZWxfMz09IkhEQiA0LVJvb20gRmxhdHMiXQ0KDQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzUgPC0gaWZlbHNlKG1wc3pfSERCJGA1cm9vbV9leGVjX3RvdGFsYCA9PSAwLCAwLCBtcHN6X0hEQiRgNXJvb21fZXhlY190b3RhbGAvdG90YWxfNV9yb29tX2V4ZWNfdW5pdHMpICogcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkdmFsdWVbcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkbGV2ZWxfMz09IkhEQiA1LVJvb20gQW5kIEV4ZWN1dGl2ZSBGbGF0cyJdDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KbXBzel9IREIkTm9fb2ZfRWxkZXJseV9pbl9ibG9jayA8LSBtcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzFfMiArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMyArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfNCArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfNQ0KYGBgDQoNCg0KYGBge3J9DQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrIDwtIHJvdW5kKG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2spDQpgYGANCg0KYGBge3J9DQpjbGluaWNzX2NvbWJpbmVkIDwtIHN0X2FzX3NmKGNsaW5pY3NfY29tYmluZWQsIGNvb3JkcyA9IGMoIlgiLCAiWSIpKQ0KY2xhc3MoY2xpbmljc19jb21iaW5lZCkNCmBgYA0KDQpgYGB7cn0NCiNhc3NpZ24gY2FwYWNpdHkgb2YgMiBwZXIgY2xpbmljDQpjbGluaWNzX2NvbWJpbmVkWydjYXBhY2l0eSddIDwtIDINCmBgYA0KDQpgYGB7cn0NCm1wc3pfSERCX2Nvb3JkcyA8LSBtcHN6X0hEQiAlPiUgc3RfY29vcmRpbmF0ZXMoKSANCmNsaW5pY3NfY29tYmluZWRfY29vcmRzIDwtIGNsaW5pY3NfY29tYmluZWQgJT4lIHN0X2Nvb3JkaW5hdGVzKCkNCmBgYA0KDQpgYGB7cn0NCmRtIDwtIGRpc3RhbmNlKG1wc3pfSERCX2Nvb3JkcywgY2xpbmljc19jb21iaW5lZF9jb29yZHMpDQphY2NfaGFuc2VuIDwtIGRhdGEuZnJhbWUoYWMobXBzel9IREIkTm9fb2ZfRWxkZXJseV9pbl9ibG9jaywgY2xpbmljc19jb21iaW5lZCRjYXBhY2l0eSwgZG0sIHBvd2VyPTAuMDEsIGZhbWlseT0iSGFuc2VuIikpDQpjb2xuYW1lcyhhY2NfaGFuc2VuKSA8LSAiYWNjSGFuc2VuIg0KYWNjX2hhbnNlbiA8LSB0YmxfZGYoYWNjX2hhbnNlbikNCkhEQl9hY2MgPC0gYmluZF9jb2xzKG1wc3pfSERCLCBhY2NfaGFuc2VuKQ0KYGBgDQoNCmBgYHtyfQ0KdG1hcF9tb2RlKCJ2aWV3IikNCmBgYA0KDQpgYGB7cn0NCnRtX3NoYXBlKG1wc3pfSERCKSsNCiAgdG1fc3ltYm9scyhzaXplID0gMC4xKSsNCnRtX3NoYXBlKEhEQl9hY2MpKw0KdG1fYnViYmxlcyhjb2wgPSAiYWNjSGFuc2VuIiwNCiAgICAgICAgICAgbj01LA0KICAgICAgICAgICBzdHlsZSA9ICJxdWFudGlsZSIsDQogICAgICAgICAgIHNpemUgPSAwLjEsDQogICAgICAgICAgIGJvcmRlci5jb2wgPSAiYmxhY2siLA0KICAgICAgICAgICBib3JkZXIubHdkID0gMSkNCmBgYA0KDQpgYGB7cn0NCm1wc3pfSERCX3NwIDwtIGFzKG1wc3pfSERCLCAiU3BhdGlhbCIpDQpjbGluaWNzX2NvbWJpbmVkX3NwIDwtIGFzKGNsaW5pY3NfY29tYmluZWQsICJTcGF0aWFsIikNCmBgYA0KDQpgYGB7cn0NCnByb2o0c3RyaW5nKGNsaW5pY3NfY29tYmluZWRfc3ApIDwtIENSUygiK2luaXQ9ZXBzZzozNDE0IikNCnNwVHJhbnNmb3JtKG1wc3pfSERCX3NwLCAiK2luaXQ9ZXBzZzozNDE0IikNCmBgYA0KDQpgYGB7cn0NCm1wc3pfSERCX3NwIDwtIG1wc3pfSERCX3NwW21wc3pfSERCX3NwQGRhdGEkU1VCWk9ORV9OPT0iVEFNQU4gSlVST05HIiwgXQ0KYGBgDQoNCmBgYHtyfQ0KZXVjRGlzdCA8LSBldWMuZGlzdHMobXBzel9IREJfc3AsIGNsaW5pY3NfY29tYmluZWRfc3ApDQpgYGANCg0KYGBge3J9DQoNCmBgYA==